using System.ComponentModel.Composition;
using XSockets.Core.Globals;
using XSockets.Core.XSocket;
using XSockets.Core.XSocket.Event;
using XSockets.Core.XSocket.Event.Attributes;
using XSockets.Core.XSocket.Interface;
using XSockets.Core.XSocket.Helpers;
using System.Collections.Generic;
using System;
using System.Linq;

namespace XSocketHandler
{
  [Export(typeof(IXBaseSocket))]
  [XBaseSocketMetadata("PickFirstHandler", Constants.GenericTextBufferSize)]
  public class PickFirstHandler : XBaseSocket
  {
      public static IList<Player> players = new List<Player>();
      
      public PickFirstHandler()
      {
          this.OnClientConnect += new System.EventHandler<XSockets.Core.XSocket.Event.Arguments.OnClientConnectArgs>(PickFirstHandler_OnClientConnect);
          this.OnClientDisConnect += new EventHandler<XSockets.Core.XSocket.Event.Arguments.OnClientDisConnectArgs>(PickFirstHandler_OnClientDisConnect);
      }

      void PickFirstHandler_OnClientDisConnect(object sender, XSockets.Core.XSocket.Event.Arguments.OnClientDisConnectArgs e)
      {
          Player playerToRemove = players.FirstOrDefault(x => x.PlayerId == e.XNode.Guid);
          players.Remove(playerToRemove);
          this.AsyncSendToAll(new { All = players, Disconnected = playerToRemove }, "OnPlayerDisconnected");
      }

      void PickFirstHandler_OnClientConnect(object sender, XSockets.Core.XSocket.Event.Arguments.OnClientConnectArgs e)
      {
          Player playerToAdd = new Player(e.XNode.Guid);
          players.Add(playerToAdd);
          this.AsyncSendToAll(new { All = players, Connected = playerToAdd }, "OnPlayerConnected");
      }

      [HandlerEvent("OnScoreChanged")]
      public void ScoreChanged(Score score)
      {
          this.AsyncSendToAll(players, "OnScoreChanged");
      }

      [HandlerEvent("OnShapeHit")]
      public void ShapeHit(GameShape shape)
      {

          Player foundPlayer = players.FirstOrDefault(x => x.PlayerId == XNode.Guid);
          foundPlayer.Score += 20;
          ScoreChanged(new Score { PlayerId = foundPlayer.PlayerId, Amount = 20 });

          if (foundPlayer.Score == 60)
          {
              this.AsyncSendToAll(foundPlayer, "OnGameEnded");
              return;
          }

          this.AsyncSendToAll(shape, "OnShapeHit");

      }

      [HandlerEvent("OnGameStarted")]
      public void GameStarted(XSocketEvent events)
      {
          foreach(Player player in players)
          {
              player.Reset();
          }
          this.AsyncSendToAll(players, "OnGameStarted");
  
      }  
      
      public override IXBaseSocket NewInstance()
      {
          return new PickFirstHandler();
      }

  }

    public class GameShape
    {
        public Guid Id { get; set; }
    }

    public class Score
    {
        public Guid PlayerId { get; set; }
        public int Amount { get; set; }
    }

    public class Player
    {
        public Player()
        {
        }

        public Player(Guid id)
        {
            PlayerId = id;
        }

        public Guid PlayerId { get; set; }
        public int Score { get; set; }

        public void Reset()
        {
            Score = 0;
        }

        public override bool Equals(object obj)
        {
            Player otherPlayer = obj as Player;
            if (otherPlayer == null)
                return false;
            return PlayerId == otherPlayer.PlayerId;
        }

        public override int GetHashCode()
        {
            return PlayerId.GetHashCode();
        }

    

    }
}
